using Gtk;
using Pango;
using Gdk;
using Irc;
enum COLS {
	SENDER,
	MSG,
	COLOR,
	NUM
}

int main (string[] args) {
	if (!Thread.supported()) {
		stderr.printf("Cannot run without threads.\n");
		return 1;
	}
	//var dir1 = GLib.Path.get_dirname(args[0]);
	//var path1 = GLib.Path.build_filename(dir1,"chat.ui");
	//stdout.printf("%s\n%s\n",args[0],path1);
    Gtk.init (ref args);
	var app1 = new MyApp();
	app1.show();
    Gtk.main();
    return 0;
}
class MyCounter:GLib.Object{
	public int no {get;set;default = 0}
}
class MyApp:GLib.Object{
	private Gtk.Builder builder1;
	private int step = 1;
	private bool color_flag = true;
	private string user_name;
	private MyCounter msg_loop;
	private Gtk.Window win1;
	private Gtk.Entry entry1;

	public void show(){
		//this.builder1 = new Gtk.Builder.from_file(ui);
		string ui_s = Resource.get_ui();
		this.builder1 = new Gtk.Builder.from_string(ui_s,ui_s.length);
		win1 = (Gtk.Window)this.builder1.get_object("win1");
		var listMsg = (Gtk.TreeView)this.builder1.get_object("listMsg");
		listMsg.set_size_request(620,410);
		win1.set_default_size (640,480);

		this.setup_msgs();
		this.setup_names();
		
		this.append_msg("sys","输入IRC服务器（默认：'chat.freenode.net:6667'）");

		Irc.Init(1); // 1 => verbose
		//var thread = new Thread<int>("SecretIRC", this.loop_msgs);
		//msg loop async
		msg_loop = new MyCounter();
		msg_loop.notify.connect((s,p)=>{
			get_msg_async.begin((obj,res)=>{
				get_msg_async.end(res);
				msg_loop.no++;
			});
		});
		msg_loop.no++;
		
		win1.destroy.connect(()=>{
			Quit();
			stdout.printf("Disconnect IRC.\n");
			Gtk.main_quit();
		});

		entry1 = (Gtk.Entry)this.builder1.get_object("entryMsg");
		entry1.activate.connect( (self)=>{
			var s = self.get_text();
			self.set_text("");
			switch(GetStep()){
			case 1:
				this.step = Irc.SetServer(s);
				this.append_msg("sys",Irc.GetHead(0));
				this.append_msg("sys","输入用户名（默认值：随机名称）");
				break;
			case 2:
				this.step = Irc.SetNick(s);
				this.user_name = s;
				this.append_msg("sys",Irc.GetHead(0));
				this.append_msg("sys","输入房间名（默认值：随机名称）");
				break;
			case 3:
				string room;
				this.step = Irc.SetRoom(s,out room);
				//this.append_user( room );
				var target = (Gtk.Label)this.builder1.get_object("labelTarget");
				target.set_text(room);
				this.append_msg("sys",Irc.GetHead(0));
				this.append_msg("sys","输入密钥（长度必须大于0）");
				self.set_visibility(false);
				break;
			case 4:
				this.step = Irc.SetKey(s);
				var h = Irc.GetHead(0);
				var top = (Gtk.Label)this.builder1.get_object("topMsg");
				top.set_text(h);
				this.append_msg("sys","连接中...");
				self.set_visibility(true);
				break;
			case 6:
				if(s==""){
					break;
				}
				var target = (Gtk.Label)this.builder1.get_object("labelTarget");
				var chan1 = target.get_text();
				Irc.Say(chan1, s);
				this.append_msg("你",s);
				break;
			}
		});
		
		win1.show_all();
	}
	public async void get_msg_async(){
		int ret;
		string from,msg;
		ret = Irc.GetMsg(out from, out msg);
		if (ret==1){
			switch(from){
			case "/join":
				GLib.Idle.add( ()=>{
					this.append_msg("JOIN",msg);
					if(msg != this.user_name)
						this.append_names(msg);
					return false;
				});
				break;
			case "/quit":
				GLib.Idle.add( ()=>{
					this.append_msg("QUIT",msg);
					this.del_from_names(msg);
					return false;
				});
				break;
			case "/part":
				GLib.Idle.add( ()=>{
					this.append_msg("leave",msg);
					this.del_from_names(msg);
					return false;
				});
				break;
			case "/names":
				GLib.Idle.add( ()=>{
					this.append_msg("USERS",msg);
					this.append_names(msg);
					return false;
				});
				break;
			default:
				GLib.Idle.add( ()=>{
					this.append_msg(from,msg);
					return false;
				});

				if((msg=="you join") && (from=="sys")){
					GLib.Idle.add( ()=>{
						var h = Irc.GetHead(1);
						var top = (Gtk.Label)this.builder1.get_object("topMsg");
						top.set_text(h);
						this.append_msg("sys",h);
						return false;
					});
				}
				break;
			}

		}else{
			break;
		}
	}
	
	private void append_msg(string sender,string msg){
		var listMsg = (Gtk.TreeView)this.builder1.get_object("listMsg");
		Gtk.ListStore store1 = (Gtk.ListStore)listMsg.get_model();
		var model1 = listMsg.get_model();
		var color1 = "#FFFFFF";
		this.color_flag = !this.color_flag;
		if(this.color_flag){
			color1 = "#EFEFEF";
		}
		if(msg.length>12){
			string prefix = "[Not Secret]";
			string p1 = msg[0:12];
			if (prefix==p1){
				color1 = "#F97A7A";
			}
		}

		Gtk.TreeIter iter;
		store1.append(out iter);
		store1.set(iter, COLS.SENDER, sender, COLS.MSG, msg,COLS.COLOR,color1);
		var path1 = model1.get_path(iter);
		listMsg.scroll_to_cell(path1,null,false,0,0);
	}
	private void setup_msgs(){
		var listMsg = (Gtk.TreeView)this.builder1.get_object("listMsg");
		listMsg.enable_grid_lines = Gtk.BOTH;
		var store1 = new Gtk.ListStore (COLS.NUM, typeof (string), typeof (string), typeof(string));
		var msg_col = (Gtk.TreeViewColumn)this.builder1.get_object("msg-column");
		var sender_col = (Gtk.TreeViewColumn)this.builder1.get_object("sender-column");
		var cmsg = (Gtk.CellRendererText)this.builder1.get_object("msg-renderer");
		var csender = (Gtk.CellRendererText)this.builder1.get_object("sender-renderer");
		msg_col.add_attribute(cmsg,"background",COLS.COLOR);
		sender_col.add_attribute(csender,"background",COLS.COLOR);
		sender_col.fixed_width=80;
		cmsg.wrap_mode = Pango.CHAR;
		cmsg.wrap_width = 450;
		csender.yalign = 0;
		listMsg.set_model(store1);
		listMsg.row_activated.connect( (tree,path,col)=>{
			//stdout.printf("%s\n",path.to_string());
			Gtk.TreeIter iter;
			var model = tree.get_model();
			model.get_iter(out iter,path);
			var v1 = Value(typeof (string));
			var v2 = Value(typeof (string));
			model.get_value(iter,0,out v1);
			model.get_value(iter,1,out v2);
			//stdout.printf("%s\n",v1.get_string());
			var entry1 = (Gtk.Entry)this.builder1.get_object("entryMsg");
			entry1.set_text(@"$(v1.get_string()):$(v2.get_string())");
		});
	}
	private void setup_names(){
		var namesList = (Gtk.TreeView)this.builder1.get_object("namesList");
		var store1 = new Gtk.ListStore (1, typeof (string));
		namesList.set_model(store1);
	}
	private void append_names( string names ){
		var namesList = (Gtk.TreeView)this.builder1.get_object("namesList");
		var store1 = (Gtk.ListStore)namesList.get_model();
		var namev = names.split(" ");
		//stdout.printf("%s %d\n",names, namev.length);
		for(int i=0;i<namev.length;i++){
			string name1=namev[i];
			if (name1[0:1]=="@") 
				name1 = namev[i][1:namev[i].length];
			Gtk.TreeIter iter;
			store1.append(out iter);
			store1.set(iter, 0, name1);
			//stdout.printf("%s\n",namev[i]);
		}
		namesList.show_all();
	}
	private void del_from_names(string name1){
		var namesList = (Gtk.TreeView)this.builder1.get_object("namesList");
		//var model1 = namesList.get_model();
		var store1 = (Gtk.ListStore) namesList.get_model();
		Gtk.TreeIter iter;
		store1.get_iter_first(out iter);
		do{
			Value val;
			store1.get_value(iter,0 ,out val);
			if(val.get_string()==name1){
				store1.remove(ref iter);
				break;
			}
		}while( store1.iter_next(ref iter) );
		namesList.show_all();
	}
}
